package com.lin.fengxiu.core;

import com.lin.fengxiu.core.configuration.ExceptionCodeConfiguration;
import com.lin.fengxiu.exception.http.HttpException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;

/**
 * @ClassName GlobalExceptionAdvice
 * @Description   @ControllerAdvice:用来标识异常处理的类
 * @Author wushaopei
 * @Date 2021/3/5 22:54
 * @Version 1.0
 */
@ControllerAdvice
public class GlobalExceptionAdvice {

    @Autowired
    ExceptionCodeConfiguration codeConfiguration;
    /**
     *  @Description 在下列的方法中抛出并处理异常信息,用来处理位置异常
     *  @param  @ExceptionHandler: 用来表示异常处理的方法
     *  @return UnifyResponse 以Json格式返回
     */
    @ExceptionHandler(value=Exception.class)
    @ResponseBody
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    public UnifyResponse handlerException(HttpServletRequest request, Exception e){
        System.out.println("hello");
        String requestUrl  = request.getRequestURI();
        String method = request.getMethod();
        UnifyResponse message = new UnifyResponse(9999, "服务异常",method + " " + requestUrl);
        return message;
    }



    /**
     * @Description 用来处理已知异常
     * @param request
     * @param e
     */
    @ExceptionHandler(HttpException.class)
    public ResponseEntity<UnifyResponse> handlerHttpException(HttpServletRequest request , HttpException e){
        String requestUrl = request.getRequestURI();
        String method = request.getMethod();

//      动态传入code码、异常信息message、发生异常的接口路径（业务方法路径）requestUrl
        UnifyResponse message = new UnifyResponse(e.getCode(),codeConfiguration.getMessage(e.getCode()),method + "" + requestUrl);
        HttpHeaders headers = new HttpHeaders();
//      针对存在的多种异常 message 格式，选择对应的headers 的contentType
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpStatus httpStatus = HttpStatus.resolve(e.getHttpStatusCode());
        ResponseEntity<UnifyResponse> r = new ResponseEntity<UnifyResponse>(message,headers,httpStatus);
        return r;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    @ResponseBody
    public UnifyResponse handleBeanValidation(HttpServletRequest request,MethodArgumentNotValidException e ){
        String requestUrl = request.getRequestURI();
        String method = request.getMethod();

        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        String message = this.formatAllErrorMessages(errors);
        return new UnifyResponse(10001,message, method + "" + requestUrl );
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    @ResponseBody
    public UnifyResponse handleConstraintViolation(HttpServletRequest request,ConstraintViolationException e ){
        String requestUrl = request.getRequestURI();
        String method = request.getMethod();
        String message = e.getMessage();
        return new UnifyResponse(10001,message, method + "" + requestUrl );
    }

    private String formatAllErrorMessages(List<ObjectError> errors){
        StringBuffer errorMsg = new StringBuffer();
        errors.forEach(error ->
            errorMsg.append(error.getDefaultMessage()).append(';'));
        return errorMsg.toString();
    }
}
